#ifndef NORMALIZED_DATATYPES_H_
#define NORMALIZED_DATATYPES_H_

#include <Judy.h>
#include "../util/queue.h"

typedef struct normalized_atomic_concept NormalizedAtomicConcept;
typedef struct normalized_conjunction NormalizedConjunction;
typedef struct normalized_existential_restriction NormalizedExists;
typedef union normalized_concept_description NormalizedConceptDescription;
typedef struct normalized_concept NormalizedConcept;

typedef struct normalized_atomic_role NormalizedAtomicRole;
typedef struct normalized_role_composition NormalizedRoleComposition;
typedef union normalized_role_description NormalizedRoleDescription;
typedef struct normalized_role NormalizedRole;

typedef struct normalized_subclass_axiom NormalizedSubClassAxiom;
typedef struct normalized_subrole_axiom NormalizedSubRoleAxiom;

typedef struct normalized_axiom NormalizedAxiom;

typedef struct normalized_tbox NormalizedTBox;

// the top concept has the id 0
#define TOP 0

enum normalized_concept_description_type {
	NORMALIZED_ATOMIC_CONCEPT, NORMALIZED_CONJUNCTION, NORMALIZED_EXISTENTIAL_RESTRICTION
};

// normalized atomic concept
struct normalized_atomic_concept {
	int id;
	char* name;
	Pvoid_t subsumers;
	Pvoid_t subsumees;
	// int number_of_concepts_to_process;
	// NormalizedConcept** concepts_to_process;
	// Pvoid_t concepts_to_process;
	struct queue concepts_to_process;
	int number_of_filler_of;
	NormalizedExists** filler_of;
 };


// conjunction
struct normalized_conjunction {
	Pvoid_t conjuncts;
};


// normalized existential restriction
struct normalized_existential_restriction {
	NormalizedRole* role;
	NormalizedConcept* filler;
	Pvoid_t subsumees;
};


// normalized concept description
union normalized_concept_description {
	NormalizedAtomicConcept* atomic;
	NormalizedConjunction* conj;
	NormalizedExists* exists;
}; 
	

// normalized concept 
struct normalized_concept {
	enum normalized_concept_description_type type;
	// list of axioms whose premise is exactly this normalized concept
	int singleton_premises_count;
	NormalizedAxiom** singleton_premises;
	// list of axioms whose premise (of size more than 1) contain this
	// normalized concept
	int containing_premises_count;
	NormalizedAxiom** containing_premises;
	NormalizedConceptDescription description;
};


///////////////////////////////////////////////////////////////////////////////
enum normalized_role_description_type {
	NORMALIZED_ATOMIC_ROLE, NORMALIZED_ROLE_COMPOSITION
};

// normalized atomic role 
struct normalized_atomic_role {
	int id;
	char* name;
	NormalizedAtomicRole** subsumers;	
	NormalizedAtomicRole** subsumees;	
};

// normalized role composition
struct normalized_role_composition {
	int role1;
	int role2;
	// TODO:
	// NormalizedAtomicRole* role1;
	// NormalizedAtomicRole* role2;
};

// normalized role description
union normalized_role_description {
	NormalizedAtomicRole* atomic;
	NormalizedRoleComposition* role_comp;
}; 

// normalized role 
struct normalized_role {
	enum normalized_role_description_type type;
	NormalizedRoleDescription description;
};
///////////////////////////////////////////////////////////////////////////////
enum normalized_axiom_type {
	NORMALIZED_SUBCLASS_AX, NORMALIZED_SUBROLE_AX
};

// for the normalize_concept function
enum axiom_side {
  LEFT_HANDSIDE, RIGHT_HANDSIDE
};

// Subclass axiom
struct normalized_subclass_axiom {
	NormalizedConcept* lhs;
	NormalizedConcept* rhs;
};

// normalized role inclusion
// lsh1 \circ lsh2 \sqsubseteq rhs
struct normalized_subrole_axiom {
	NormalizedRole* lhs;
	NormalizedRole* rhs;
};

// inclusion axiom
union normalized_axiom_body {
        NormalizedSubClassAxiom* subclass_ax;
        NormalizedSubRoleAxiom* subrole_ax;
};


struct normalized_axiom {
	enum normalized_axiom_type type;
	union normalized_axiom_body body;
};


// Normalized TBox
struct normalized_tbox {
	NormalizedAxiom** axioms;
	int axiom_count;
};

#endif /*NORMALIZED_DATATYPES_H_*/
